﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NewRetail.Application.Components.WeChat.Configurations;
using NewRetail.Application.Components.WeChat.Services.HttpClients;
using NewRetail.Application.Core;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;

namespace NewRetail.Application.Components.WeChat.Services.BackgroundServices
{
    /// <summary>
    /// 定时刷新微信商户平台证书
    /// </summary>
    public class WxpayCertificateRefreshingWorker : ApplicationService, ITransientDependency
    {
        #region params
        private readonly ILogger _logger;
        private readonly WxpayOptions _wxpayOptions;
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly RedLockFactoryWrapper _redLockFactoryWrapper;
        //private readonly CertificateManager _certificateManager;
        private readonly IWechatTenpayHttpClientFactory _wechatTenpayHttpClientFactory;
        #endregion

        #region 构造
        public WxpayCertificateRefreshingWorker(ILogger<WxpayCertificateRefreshingWorker> logger,
            RedLockFactoryWrapper redLockFactoryWrapper, IUnitOfWorkManager unitOfWorkManager, /*CertificateManager certificateManager,*/
            IOptions<WxpayOptions> wxpayOptions, IWechatTenpayHttpClientFactory wechatTenpayHttpClientFactory)
        {
            _logger = logger;
            _redLockFactoryWrapper = redLockFactoryWrapper;
            _unitOfWorkManager = unitOfWorkManager;
            //_certificateManager = certificateManager;
            _wxpayOptions = wxpayOptions.Value;
            _wechatTenpayHttpClientFactory = wechatTenpayHttpClientFactory;
        }
        #endregion

        #region method
        [UnitOfWork]
        public virtual async Task Execute()
        {
            try
            {
                _logger.LogInformation(DateTime.Now.ToString() + "[WxpayCertificateRefreshing]");
                IList<Task> tasks = new List<Task>();
                //多个商户平台需要都刷新
                foreach (var wxpayMerchant in _wxpayOptions.Merchants)
                {
                    Task task = TryRefreshWxpayCertificateAsync(wxpayMerchant);
                    tasks.Add(task);
                }

                await Task.WhenAll(tasks);

            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
                throw;
            }
        }
        #endregion

        #region 微信商户平台证书
        [UnitOfWork]
        private async Task TryRefreshWxpayCertificateAsync(WxpayOptions.WechatMerchant wxpayMerchant, CancellationToken cancellationToken = default)
        {
            if(wxpayMerchant == null)
            {
                _logger.LogWarning("未找到微信商户配置项。");
                return;
            }
            if (string.IsNullOrEmpty(wxpayMerchant.MerchantId))
            {
                _logger.LogWarning("微信商户号不能为空。");
                return;
            }
            
            // resource 锁定的对象
            // expiryTime 锁定过期时间，锁区域内的逻辑执行如果超过过期时间，锁将被释放
            // waitTime 等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
            // retryTime 等待时间内，多久尝试获取一次
            using var distributedLock = await _redLockFactoryWrapper.RedLockFactory.CreateLockAsync(
                resource: $"{nameof(WxpayCertificateRefreshingWorker)}",
                expiryTime: TimeSpan.FromMinutes(1),
                waitTime: TimeSpan.FromMinutes(1),
                retryTime: TimeSpan.FromSeconds(30));

            if (distributedLock.IsAcquired)
            {
                var client = _wechatTenpayHttpClientFactory.Create(wxpayMerchant.MerchantId);
                var request = new QueryCertificatesRequest();
                var response = await client.ExecuteQueryCertificatesAsync(request, cancellationToken: cancellationToken);
                if (response.IsSuccessful())
                {
                    // 注意：如果启用了 AutoDecryptResponseSensitiveProperty，则无需再手动执行下面被注释的解密方法
                    //client.DecryptResponseSensitiveProperty(response);
                    foreach (var cert in response.CertificateList)
                    {
                        //_certificateManager.SetCertificate(cert.SerialNumber, cert.EncryptCertificate.CipherText);
                        //_certificateManager.AddEntry(new CertificateEntry(cert));
                        client.CertificateManager.AddEntry(new CertificateEntry(cert));
                    }

                    _logger.LogInformation("刷新微信商户平台证书成功。");
                }
                else
                {
                    _logger.LogWarning(
                        "刷新微信商户平台证书失败（状态码：{0}，错误代码：{1}，错误描述：{2}）。",
                        response.RawStatus, response.ErrorCode, response.ErrorMessage
                    );
                }
            }
            else
            {
                _logger.LogInformation("未能拿到锁，存在并发");
            }
        }
        #endregion
    }
}
